package com.itheima.server.service;

import cn.hutool.core.collection.CollUtil;
import com.itheima.commons.utils.Constants;
import com.itheima.server.exception.BusinessException;
import com.itheima.server.interceptor.UserHolder;
import com.itheima.tanhua.autoconfig.template.OssTemplate;
import com.itheima.tanhua.dubbo.api.MovementsApi;
import com.itheima.tanhua.dubbo.api.UserInfoApi;
import com.itheima.tanhua.model.domain.PageResult;
import com.itheima.tanhua.model.domain.UserInfo;
import com.itheima.tanhua.model.mongo.Movement;
import com.itheima.tanhua.model.mongo.MovementTimeLine;
import com.itheima.tanhua.model.vo.ErrorResult;
import com.itheima.tanhua.model.vo.MovementsVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementsApi movementsApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate redisTemplate;


    public void publishMovements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断动态文本是否存在
        if (movement.getTextContent() == null) {
            throw new BusinessException(ErrorResult.contentError());
        }

        //获取用户id
        Long userId = UserHolder.getUserId();
        //获取图片上传地址
        List<String> urls = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String imgUrl = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            urls.add(imgUrl);
        }
        //将所需数据封装到对象中
        movement.setUserId(userId);
        movement.setMedias(urls);
        //保存动态
        movementsApi.publishMovements(movement);


    }

    /**
     * 查询动态
     *
     * @param page
     * @param pagesize
     * @param userId
     * @return
     */
    public PageResult findByUserId(Integer page, Integer pagesize, Long userId) {
        //调用api查询所有动态
        PageResult pageResult = movementsApi.findByUserId(page, pagesize, userId);
        if (pageResult.getItems() == null) {
            return pageResult;
        }
        //查询个人详细信息
        UserInfo userInfo = userInfoApi.findById(userId);

        List<Movement> items = (List<Movement>) pageResult.getItems();

        //将个人信息与动态信息封装到vo类中
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement item : items) {
            MovementsVo movementsVo = MovementsVo.init(userInfo, item);
            voList.add(movementsVo);
        }
        pageResult.setItems(voList);

        return pageResult;
    }

    /**
     * 好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findFriendMovements(Integer page, Integer pagesize) {

        Long userId = UserHolder.getUserId();

        //获取好友动态内容
        List<Movement> movements = movementsApi.findTimeLine(page, pagesize, userId);

        return getPageResult(page, pagesize, movements);
    }

    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> movements) {
        if (CollUtil.isEmpty(movements)) {
            return new PageResult();
        }

        //获取动态内容中的好友id
        List<Long> userIds = CollUtil.getFieldValues(movements, "userId", Long.class);

        //查询发布动态好友的具体信息
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds, null);

        List<MovementsVo> list = new ArrayList<>();

        //遍历动态内容，将每一条动态内容与个人信息封装到vo中，构造返回值
        for (Movement movement : movements) {

            UserInfo userInfo = userInfoMap.get(movement.getUserId());

            MovementsVo vo = MovementsVo.init(userInfo, movement);

            list.add(vo);
        }

        return new PageResult(page, pagesize, 0, list);
    }

    /**
     * 推荐动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {

        String key = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();

        //从redis中获取推荐动态数据
        String redisPidData = (String) redisTemplate.opsForValue().get(key);

        //构造一个空集合
        List<Movement> list = Collections.EMPTY_LIST;

        //判断数据是否为空
        if (StringUtils.isEmpty(redisPidData)) {
            //为空，调用api随机生成10条数据
            list = movementsApi.randomMovements(pagesize);
        } else {
            //不为空，对redis中的pid进行处理调用api查询数据
            //切割redis中取出的数据方便处理
            String[] split = redisPidData.split(",");
            //判断当前页得起始条数是否少于数据总数
            //小于说明没有数据可以查询了，直接返回空值
            if ((page - 1) * pagesize > split.length) {
                return new PageResult();
            }
            List<Long> pids = Arrays.stream(split).skip((page - 1) * pagesize)
                    .limit(pagesize)
                    .map(e -> Long.valueOf(e))
                    .collect(Collectors.toList());

            list = movementsApi.findMovementsByPids(pids);

        }

        //构造返回值
        PageResult pageResult = getPageResult(page, pagesize, list);

        return pageResult;
    }

    /**
     * 根据用户id查询动态详情
     *
     * @return
     */
    public MovementsVo findByMovmentId(String id) {

        //调用api查询动态数据
        Movement movement = movementsApi.findByMovmentId(id);
        //判断是否为空
        if (movement == null) {
            return null;
        }
        //取出用户id，查询用户详情
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        //封装返回值
        return MovementsVo.init(userInfo, movement);
    }
}